package com.wonderful.map

import android.content.Context
import android.graphics.Bitmap
import android.graphics.PointF
import android.util.AttributeSet
import android.util.Log
import android.widget.FrameLayout
import com.wonderful.image.ImageSource
import com.wonderful.image.ImageViewState
import com.wonderful.image.ScaleImageView
import com.wonderful.image.ScaleImageView.DefaultOnStateChangedListener
import com.wonderful.image.utils.PointUtil
import com.wonderful.map.bean.GridPositionBean
import com.wonderful.map.bean.PointBean
import com.wonderful.map.bean.PositionBean
import com.wonderful.map.bean.VirtualObstacleBean
import com.wonderful.map.view.FeaturePathView
import com.wonderful.map.view.PointView
import com.wonderful.map.view.PointsView
import com.wonderful.map.view.VirtualCleanView
import com.wonderful.map.view.VirtualObstacleView

/**
 * Desc: Map View
 * @Author: wonderful
 * @Time: 2023/5/10 10:31
 */
class MapView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    defStyleRes: Int = 0
) : FrameLayout(context, attrs, defStyleAttr, defStyleRes) {

    companion object {
        private const val TAG = "MapView"
    }

    private val mLayoutParams: LayoutParams =
        LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
    private val mMapView: PinView
    private var mMapWidth: Int = 0
    private var mMapHeight: Int = 0

    // 位置点
    private var isShowLocation = false   // 是否显示
    private var mLocationSize = 30f       // 大小
    private val mLocationPointF = PointF()

    // 功能点
    private val mPointsView: PointsView
    private var isShowPoints = false
    private var isPointClickable = true  // 点是否能被点击

    // 虚拟墙
    private val mVirtualObstacleView: VirtualObstacleView
    private var isShowVirtualObstacle = false

    // 清洁区域&路线
    private val mVirtualCleanView: VirtualCleanView
    private var isShowVirtualClean = false

    // 特征路径
    private val mFeaturePathView: FeaturePathView
    private var isShowFeaturePath = false


    private var mMatrixRotateAngle = 0f  // 地图矩阵旋转的角度

    // 监听回调
    private var mMapViewListener: MapViewListener? = null

    init {
        mMapView = PinView(context)
        initMapView()

        mPointsView = PointsView(context).apply { layoutParams = mLayoutParams }
        mVirtualObstacleView = VirtualObstacleView(context).apply { layoutParams = mLayoutParams }
        mVirtualCleanView = VirtualCleanView(context).apply { layoutParams = mLayoutParams }
        mFeaturePathView = FeaturePathView(context).apply { layoutParams = mLayoutParams }
    }

    private fun initMapView() {
        mMapViewListener?.onLoadStart()
        mMapView.apply {
            layoutParams = mLayoutParams
            maxScale = 8f
            setMinimumDpi(320)
            setDoubleTapZoomStyle(ScaleImageView.ZOOM_FOCUS_CENTER)
            setPanLimit(ScaleImageView.PAN_LIMIT_CENTER)
            setOnImageEventListener(object : ScaleImageView.DefaultOnImageEventListener() {
                override fun onReady() {
                    Log.e(TAG, "map-onReady")
                    mMapViewListener?.onLoadFinish()
                    Log.e(TAG, "vTranslate=${mMapView.vTranslate} scale=${mMapView.scale}")
                }

                override fun onImageLoadError(e: Exception?) {
                    super.onImageLoadError(e)
                    Log.e(TAG, "map-onImageLoadError")
                }

                override fun onTileLoadError(e: Exception?) {
                    super.onTileLoadError(e)
                    Log.e(TAG, "map-onTileLoadError")
                }

                override fun onClick(view: ScaleImageView, imagePoint: PointF, eventPoint: PointF) {
                    Log.e(TAG, "map-onClick：imgPoint=$imagePoint eventPoint=$eventPoint")
                }
            })

            setOnStateChangedListener(object : DefaultOnStateChangedListener() {
                override fun onScaleChanged(newScale: Float, origin: Int) {
                }

                override fun onCenterChanged(newCenter: PointF?, origin: Int) {
                    refreshView()
                }

            })

        }
        addView(mMapView)
    }

    private fun getTranslate() = mMapView.vTranslate
    private fun getScale() = mMapView.scale

    private fun refreshView() {
        val imgMatrix = mMapView.curMatrix
        mMatrixRotateAngle = PointUtil.getMatrixRotateAngle(imgMatrix)

        val vTranslate = getTranslate()
        val scale = getScale()

        if (isShowLocation) {
            // val pf = PointUtil.getAbsolutePoint(mLocationPointF, imgMatrix)
            // mMapView.setPinPointF(pf)
        }

        if (isShowPoints) {
            mPointsView.refreshView(vTranslate, scale)
        }

        if (isShowVirtualObstacle) {
            mVirtualObstacleView.refreshView(vTranslate, scale)
        }

        if (isShowVirtualClean) {
            mVirtualCleanView.refreshView(vTranslate, scale)
        }

        if (isShowFeaturePath) {
            mFeaturePathView.refreshView(vTranslate, scale)
        }

    }

    // --------------------------------- 点相关方法 start -------------------------------------------
    /**
     * 获取 pointsView
     */
    fun getPointsView(): PointsView = mPointsView

    /**
     * 设置点是否可点击
     */
    fun setPointViewClickable(isClickable: Boolean) {
        isPointClickable = isClickable
    }

    /**
     * 添加点
     */
    fun addPoint(point: PointBean) {
        mPointsView.addPoint(point, getTranslate(), getScale(), getMapHeight()).apply {
            setOnClickListener {
                if (isPointClickable) mMapViewListener?.onPointClick(this)
            }
        }
    }

    /**
     * 设置是否显示功能点
     */
    fun setShowPointsView(isShow: Boolean) {
        if (isShowPoints == isShow) return
        isShowPoints = isShow
        if (isShow) {
            addView(mPointsView)
        } else {
            removeView(mPointsView)
        }
    }

    /**
     * 设置多个点
     */
    fun setPointsData(pointList: List<PointBean>) {
        mPointsView.setPoints(pointList, getTranslate(), getScale(), getMapHeight())
        for (pointView in mPointsView.getPointViews()) {
            pointView.setOnClickListener {
                if (isPointClickable) mMapViewListener?.onPointClick(pointView)
            }
        }
    }

    // --------------------------------- 点相关方法 end ---------------------------------------------


    // --------------------------------- 虚拟障碍物相关方法 start -----------------------------------
    /**
     * 是否显示虚拟障碍物
     */
    fun setShowVirtualObstacleView(isShow: Boolean) {
        if (isShowVirtualObstacle == isShow) return
        isShowVirtualObstacle = isShow
        if (isShow) {
            addView(mVirtualObstacleView)
        } else {
            removeView(mVirtualObstacleView)
        }
    }

    /**
     * 设置全部虚拟墙
     */
    fun setVirtualWalls(virtualWalls: List<VirtualObstacleBean>) {
        mVirtualObstacleView.setVirtualObstacles(virtualWalls, getTranslate(), getScale())
    }

    /**
     * 获取清洁区域&路径 view
     */
    fun getVirtualObstacleView() = mVirtualObstacleView

    // --------------------------------- 虚拟障碍物相关方法 end --------------------------------------


    // --------------------------------- 清洁区域路径相关方法 start -----------------------------------
    /**
     * 是否显示清洁区域&路径
     */
    fun setShowVirtualCleanView(isShow: Boolean) {
        if (isShowVirtualClean == isShow) return
        isShowVirtualClean = isShow
        if (isShow) {
            addView(mVirtualCleanView)
        } else {
            removeView(mVirtualCleanView)
        }
    }

    /**
     * 设置清洁区域&路径 数据
     */
    fun setVirtualCleanData(virtualObstacleBean: VirtualObstacleBean) {
        mVirtualCleanView.addVirtualObstacle(virtualObstacleBean, getTranslate(), getScale())
    }

    /**
     * 设置清洁区域中的规划路径
     */
    fun setPlanPathData(planPath: List<List<GridPositionBean>>) {
        mVirtualCleanView.setPlanPathLines(planPath, getTranslate(), getScale(), getMapHeight())
    }

    /**
     * 获取清洁区域&路径 view
     */
    fun getVirtualCleanView() = mVirtualCleanView

    // --------------------------------- 清洁区域路径相关方法 end -------------------------------------


    // --------------------------------- 特征路径相关方法 start --------------------------------------
    /**
     * 是否显示特征路径
     */
    fun setShowFeaturePathView(isShow: Boolean) {
        if (isShowFeaturePath == isShow) return
        isShowFeaturePath = isShow
        if (isShow) {
            addView(mFeaturePathView)
        } else {
            removeView(mFeaturePathView)
        }
    }

    /**
     * 设置特征路径
     */
    fun setFeaturePathData(points: List<GridPositionBean>) {
        mFeaturePathView.setPathPoints(points, getTranslate(), getScale(), getMapHeight())
    }

    // --------------------------------- 特征路径相关方法 end ----------------------------------------


    // --------------------------------- pinView 相关方法 start -------------------------------------
    /**
     * 获取地图控件
     */
    fun getMapView() = mMapView

    fun getMapHeight(): Int {
        if (mMapHeight == 0) mMapHeight = mMapView.height
        return mMapHeight
    }

    fun getMapWidth(): Int {
        if (mMapWidth == 0) mMapWidth = mMapView.width
        return mMapWidth
    }

    fun setImage(resId: Int) {
        mMapView.setImage(ImageSource.resource(resId).dimensions(8000, 8000))
    }

    fun setImage(
        source: ImageSource,
        previewSource: ImageSource? = null,
        state: ImageViewState? = null
    ) {
        mMapView.setImage(source, previewSource, state)
    }

    // 位置点相关
    fun setLocationImg(bitmap: Bitmap) {
        mMapView.setPinImage(bitmap)
    }

    fun setShowLocation(isShow: Boolean) {
        if (isShowLocation == isShow) return
        isShowLocation = isShow
        mMapView.setPinShow(isShow)
    }

    /**
     * 设置位置
     */
    fun setLocation(pointF: PointF, angle: Float) {
        val mPointF = PointUtil.getAbsolutePoint(pointF, mMapView.curMatrix)
        mMapView.apply {
            setPinPointF(mPointF)
            setPinAngle(angle + mMatrixRotateAngle)
        }
        mLocationPointF.set(mPointF)
    }

    /**
     * 设置位置
     */
    fun setLocation(position: PositionBean) {
        //val pointF = PointF(position.gridPosition.x, getMapHeight() - position.gridPosition.y)
        val pointF = PointF(position.gridPosition.x, position.gridPosition.y)
        setLocation(pointF, position.angle)
    }

    // --------------------------------- pinView 相关方法 end ---------------------------------------

    /**
     * 设置地图监听
     */
    fun setMapListener(listener: MapViewListener) {
        mMapViewListener = listener
    }

    interface MapViewListener {
        // 加载开始
        fun onLoadStart()

        // 加载结束
        fun onLoadFinish()

        // 点击功能点
        fun onPointClick(pointView: PointView)
    }
}